// ***** BEGIN LICENSE BLOCK *****
// Version: MPL 1.1/GPL 2.0/LGPL 2.1
//
// The contents of this file are subject to the Mozilla Public License Version
// 1.1 (the "License"); you may not use this file except in compliance with
// the License. You may obtain a copy of the License at
// http://www.mozilla.org/MPL/
//
// Software distributed under the License is distributed on an "AS IS" basis,
// WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
// for the specific language governing rights and limitations under the
// License.
//
// The Initial Developer of the Original Code is
//   Axel Nennker http://axel.nennker.de/ .
// Created by the Initial Developer are Copyright (C) 2011
// the Initial Developer. All Rights Reserved.

var OpenIdNascarUrlbar = {
    consoleService : null,
    _preferencesWindow : null,
    
    urlbarPreferencesOnCommand : function(aEvent) {
      var doc = aEvent.target.ownerDocument;
      var panel = doc.getElementById("openidnascarpanel");
      if (panel) {
        panel.hidePopup();
      }
      OpenIdNascarUrlbar.openPreferences();
    },
    
    getAllEntries: function(inputField) {
      try {
//        OpenIdNascarUrlbar._logMessage('getAllEntries inputField.tagName=' + inputField.tagName);
        var aFieldname = inputField.id;
        if (!aFieldname) {
          aFieldname = inputField.name;
//          OpenIdNascarUrlbar._logMessage('getAllEntries name aFieldname=' + aFieldname);
        } else {
//          OpenIdNascarUrlbar._logMessage('getAllEntries id aFieldname=' + aFieldname);
        }
        if (!aFieldname) {
//          OpenIdNascarUrlbar._logMessage('getAllEntries !aFieldname');
        }
        var mDBConn = Components.classes["@mozilla.org/satchel/form-history;1"]
              .getService(Components.interfaces.nsIFormHistory2)
              .DBConnection;
        var result = [];
        
        var resultOk = false, statement;
        try {
          statement = mDBConn.createStatement(
              "SELECT id, fieldname, value, timesUsed, firstUsed, lastUsed" +
              "  FROM moz_formhistory" +
              " WHERE fieldname = :fieldname");
          statement.params["fieldname"] = aFieldname;
          while (statement.executeStep()) {
            var fieldname = statement.row.fieldname;
            var value = statement.row.value;
//            OpenIdNascarUrlbar._logMessage('fieldname=' + fieldname + ' value=' + value);
            result.push({
              id:    statement.row.id,
              name:  fieldname,
              value: value,
              used:  statement.row.timesUsed,
              first: statement.row.firstUsed,
              last:  statement.row.lastUsed,
              place: []}
            );
          }
    
          resultOk = true;
        } catch(ex) {
          OpenIdNascarUrlbar._logMessage('getAllEntries:Exception: ' + ex);
          dump('getAllEntries:Exception: ' + ex);
        } finally {
          if (statement) {
            try {
              statement.reset();
            } catch(ex) {
              dump('_closeStatement::reset Exception: ' + ex);
            }
            try {
              statement.finalize();
            } catch(ex) {
              dump('_closeStatement::finalize Exception: ' + ex);
            }
          }
        }
        return result;
      } catch (e) {
        Components.utils.reportError(e);
      }
    },
    
    getVisitedPlaces : function _getVisitedPlaces() {
      var mPlacesDbConn = Components.classes["@mozilla.org/browser/nav-history-service;1"]
            .getService(Components.interfaces.nsPIPlacesDatabase).DBConnection;
      var statement;
      try {
        statement = mPlacesDbConn.createStatement(
          "SELECT p.url, p.title, p.rev_host, p.visit_count, h.visit_date " +
          "  FROM moz_places p, moz_historyvisits h " +
          " WHERE p.id = h.place_id " +
          " ORDER BY h.visit_date DESC " );
        
        
        var result = [];
        while (statement.executeStep()) {
          var url = ""+statement.row["url"];
          var host = ""+statement.row["rev_host"];
          var title = ""+statement.row["title"];
          var count = statement.row["visit_count"];
          var date = statement.row["visit_date"];
          
//          OpenIdNascarUrlbar._logMessage("url=" + url + " host=" + host + " title=" + title);

          result.push({
            url  : url,
            host : host,
            title: title,
            count: count,
            date : date}
          );
        }
      } catch(ex) {
        Components.utils.reportError(e);
        dump('getVisitedPlaces:Exception: ' + ex);
      } finally {
        if (statement) {
          statement.finalize();
        }
      }
    },
    
    _logMessage : function _logMessage(message)
    {
//      if(!OpenIdNascarUrlbar.consoleService) {
//        OpenIdNascarUrlbar.consoleService = Services.console;
//      }
//      OpenIdNascarUrlbar.consoleService.logStringMessage( "OpenIdNascar:" + message);
    },

    DNDObserver : {
      onDragStart: function (aEvent, aXferData, aDragAction)
      {
        try {
          var OpenIdStorage = Components.classes['@openinfocard.com/openidstorage;1']
          .getService().wrappedJSObject;
          var preferredOpenidProvider = OpenIdStorage.getPreferredOpenID();
          if (preferredOpenidProvider) {
            preferredOpenidProvider = unescape(preferredOpenidProvider);
            var urlString = preferredOpenidProvider + "\n" + "openid";
            var htmlString = "<a href=\"" + preferredOpenidProvider + "\">" + preferredOpenidProvider + "</a>";
  
            aXferData.data = new TransferData();
            aXferData.data.addDataForFlavour("text/x-moz-url", urlString);
            aXferData.data.addDataForFlavour("text/unicode", preferredOpenidProvider);
            aXferData.data.addDataForFlavour("text/plain", preferredOpenidProvider);
            aXferData.data.addDataForFlavour("text/html", htmlString);
  
            aDragAction.action =
              Components.interfaces.nsIDragService.DRAGDROP_ACTION_COPY |
              Components.interfaces.nsIDragService.DRAGDROP_ACTION_MOVE |
              Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
  
          } else {
//            OpenIdNascarUrlbar._logMessage("onDragStart !preferredOpenidProvider");
          }
        } catch (e) {
          Components.utils.reportError(e);
        }
      }
    },
    
    urlbarDrag : function urlbarDrag(event, win) {
      try {
//        OpenIdNascarUrlbar._logMessage("urlbarDrag target=" + event.target.id);
        nsDragAndDrop.startDrag(event, OpenIdNascarUrlbar.DNDObserver);
      } catch (e) {
        Components.utils.reportError(e);
      }
    },
    
    openGetOpenIdTab : function _openGetOpenIdTab(aEvent) {
      gBrowser.selectedTab = gBrowser.addTab("https://openid.net/get-an-openid/");  
    },
    
    openPreferences : function() {
      if (null == OpenIdNascarUrlbar._preferencesWindow || OpenIdNascarUrlbar._preferencesWindow.closed) {
    	/* @AMOSuppressWarning UnsafeJS */
        let instantApply = Application.prefs.getValue("browser.preferences.instantApply", true);
        let features =
          "chrome,titlebar,toolbar,centerscreen" +
          (instantApply ? ",dialog=no" : ",modal");
    
        OpenIdNascarUrlbar._preferencesWindow =
          window.openDialog(
            "chrome://openidnascar/content/preferences.xul",
            "openidnascar-preferences-window", features);
      }
    
      OpenIdNascarUrlbar._preferencesWindow.focus();
    },

    popupNotification : function _popupNotification(aEvent, result) {
      var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
      var browserBundle = bundleService.createBundle("chrome://openidnascar/locale/openid.properties");
      var OpenIdStorage = Components.classes['@openinfocard.com/openidstorage;1']
        .getService().wrappedJSObject;
      var preferredOpenidProvider = OpenIdStorage.getPreferredOpenID();
      var openids = OpenIdStorage.getAllOpenIDs();
//      OpenIdNascarUrlbar._logMessage("openids.length=" + openids.length);
      if (openids.length == 0 && !preferredOpenidProvider) {
        var message = browserBundle.GetStringFromName("openid.enteropenid"); 
        OpenIdNascarUrlbar.popupMessage(aEvent, message);
        return;
      }
      var temp = "";
      for (var i=0; i<result.length; i++) {
        temp = temp + result[i].value;
        if (i+1 < result.length) {
          temp = temp + ":";
        }
      }
      var doc = aEvent.target.ownerDocument;
//      OpenIdNascarUrlbar._logMessage("urlbar doc.location.href=" + doc.location.href);
      var panel = doc.getElementById("openidnascarpanel");
      if (panel) {
        if ((panel.state === "open") || (panel.state === "showing")) {
          return;
        }
        
        var message = browserBundle.GetStringFromName("openidnascar.overlay.description");
        var description = doc.getElementById("openidnascarpaneldescription");
        description.setAttribute("value", message);

        var box = doc.getElementById("openidnascarpanelvbox");
        while (box.lastChild) {
          box.removeChild(box.lastChild); 
        }
        var found = false;
        for (var i=0; i<openids.length; i++) {
          var prepend = false;
          var rowBox = doc.createElementNS(
                  "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                  "hbox");
          var image = doc.createElementNS(
                  "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                  "image");
          var claimed_id = openids[i].username;
          var dataUrl = OpenIdStorage.getImage(claimed_id, null);
  		  if (dataUrl) {
//  			OpenIdNascarUrlbar._logMessage("popupNotification dataUrl=" + dataUrl);
  			image.setAttribute("src", dataUrl);
  		  } else {
  			image.setAttribute("src", "chrome://openidnascar/content/openid-16x16.gif");
  		  }
          image.setAttribute("width", "32");
          image.setAttribute("height", "32");
          rowBox.appendChild(image);
          var button = doc.createElementNS(
                  "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                  "button");
          var label = unescape(openids[i].username);
          if (openids[i].username == preferredOpenidProvider) {
            found = true;
          }
          var claimed_id = openids[i].username;
          var openidname = OpenIdStorage.getOpenIDName(claimed_id);
          if (openidname) {
              button.setAttribute("label", openidname);
          } else {
              button.setAttribute("label", label);
          }
          for (var r=0; r<result.length; r++) {
            if (label.indexOf(result[r].value) > -1) {
              button.setAttribute("style", "font-size:larger");
              prepend = true;
            }
          }
          button.setUserData("openid", label, null);
//          OpenIdNascarUrlbar._logMessage("urlbar popupNotification label=" + label + " temp=" + temp);
          var callback = function(aEvent) {
            var label = aEvent.target.getUserData("openid");
            OpenIdNascarUrlbar.insertOpenid(label, null);
            panel.hidePopup();
            while (box.lastChild) {
              box.removeChild(box.lastChild); 
            }
          };
          button.addEventListener("command", callback, false);
          rowBox.appendChild(button);
          if (prepend === true) {
            box.insertBefore(rowBox, box.firstChild);
          } else {
            box.appendChild(rowBox);
          }
        }
        
        if (!found) { // insert user entered openid on top position
          var rowBox = doc.createElementNS(
            "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
            "hbox");
          var image = doc.createElementNS(
            "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
            "image");
          image.setAttribute("src", "chrome://openidnascar/content/openid-32x32.png");
          image.setAttribute("width", "32");
          image.setAttribute("height", "32");
          image.setAttribute("id", preferredOpenidProvider);
          var imageCallback = function(aEvent) {
              var label = aEvent.target.getAttribute("id");
              OpenIdNascarUrlbar.insertOpenid(label, null);
              panel.hidePopup();
              while (box.lastChild) {
                box.removeChild(box.lastChild); 
              }
            };
          image.addEventListener("click", imageCallback, false);
          rowBox.appendChild(image);
          var button = doc.createElementNS(
              "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
              "button");
          var openidname = OpenIdStorage.getOpenIDName(preferredOpenidProvider);
          if (openidname) {
              button.setAttribute("label", openidname);
          } else {
              button.setAttribute("label", preferredOpenidProvider);
          }
          button.setUserData("openid", preferredOpenidProvider, null);
          var callback = function(aEvent) {
            var label = aEvent.target.getUserData("openid");
            OpenIdNascarUrlbar.insertOpenid(label, null);
            panel.hidePopup();
            while (box.lastChild) {
              box.removeChild(box.lastChild); 
            }
          };
          button.addEventListener("command", callback, false);
          rowBox.appendChild(button);
          box.insertBefore(rowBox, box.firstChild);
        }
        
        panel.close=true;
        var anchor = doc.getElementById("openid-nascar-url-bar-image"); 
        var position = "after_start";
        var x = 0;
        var y = 0;
        var isContextMenu = false;
        var attributesOverride = false;
        var triggerEvent = aEvent;
        panel.openPopup(
            anchor , 
            position , 
            x , y , 
            isContextMenu, 
            attributesOverride, 
            triggerEvent );
      } else {
//        OpenIdNascarUrlbar._logMessage("urlbarClick panel is not defined");
      }

    },

    popupMessage : function _popupMessage(aEvent, message) {
      var doc = aEvent.target.ownerDocument;
      var panel = doc.getElementById("openidnascarpanel");
      if (panel) {
        var description = doc.getElementById("openidnascarpaneldescription");
        description.setAttribute("value", message);
        
        var box = doc.getElementById("openidnascarpanelvbox");
        while (box.lastChild) {
          box.removeChild(box.lastChild); 
        }
       
        panel.close=true;
        var anchor = doc.getElementById("openid-nascar-url-bar-image"); 
        var position = "after_start";
        var x = 0;
        var y = 0;
        var isContextMenu = false;
        var attributesOverride = false;
        var triggerEvent = aEvent;
        panel.openPopup(
            anchor , 
            position , 
            x , y , 
            isContextMenu, 
            attributesOverride, 
            triggerEvent );
      } else {
//        OpenIdNascarUrlbar._logMessage("urlbarClick panel is not defined");
      }

    },

    insertOpenid : function _insertOpenid(preferredOpenidProvider, inputField) {
      var doc = gBrowser.selectedBrowser.contentDocument;
      if (!inputField) {
        Components.utils.import("resource://openidnascar/inputfields.jsm");
        inputField = findBestInputField(doc, OpenIdNascarUrlbar._logMessage);
      }
      if (inputField) {
        preferredOpenidProvider = unescape(preferredOpenidProvider);
//        OpenIdNascarUrlbar._logMessage("urlbarClick doc.location.href=" + doc.location.href);
        inputField.setAttribute("value", preferredOpenidProvider);
        var onchange = inputField.getAttribute("onchange");
  //      OpenIdNascarUrlbar._logMessage("urlbarClick onchange=" + onchange);
        if (onchange) {
          // notify element of change
          var evnt = document.createEvent( "Event");
          evnt.initEvent( "change", true, true);
          inputField.dispatchEvent(evnt);
          // but do not submit form
        } else {
          var form = inputField.form;
          if (!form) {
            {
              // special janrain code
              var parentDoc = inputField.ownerDocument; // not doc because of frames
              var wa_signin = parentDoc.getElementById("wa_signin"); // janrain
              if (wa_signin) {
                var event = parentDoc.createEvent( "Event");
                event.initEvent( "click", true, true);
                wa_signin.dispatchEvent( event);
              }
            }            
//            OpenIdNascarUrlbar._logMessage("urlbarClick no form in " + inputField.ownerDocument.location.href);
            return;
          }
          inputField.setAttribute("value", preferredOpenidProvider);
          form.submit();
        }
      } else {
//        OpenIdNascarUrlbar._logMessage("insertOpenid: no inputField found");
      }
    },

    noOpenIdYet : function _noOpenIdYet(aEvent) {
      var doc = aEvent.target.ownerDocument;
      var panel = doc.getElementById("openidnascarpanel");
      if (!panel) {
//        OpenIdNascarUrlbar._logMessage("urlbarClick panel is not defined");
        return;
      }
      var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
      var browserBundle = bundleService.createBundle("chrome://openidnascar/locale/openid.properties");
      
      var message = browserBundle.GetStringFromName("openid.noopenidyet");
      var description = doc.getElementById("openidnascarpaneldescription");
      description.setAttribute("value", message);
      
      var box = doc.getElementById("openidnascarpanelvbox");
      while (box.lastChild) {
        box.removeChild(box.lastChild); 
      }
     
      var button = doc.createElementNS(
        "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
        "button");
      message = browserBundle.GetStringFromName("openid.oidfgetanopenid");
      button.setAttribute("label", message);
      var callback = function(aEvnt) {
        panel.hidePopup();
        OpenIdNascarUrlbar.openGetOpenIdTab(aEvnt);
      };
      button.addEventListener("command", callback, false);
      box.insertBefore(button, box.firstChild);
      
      button = doc.createElementNS(
        "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
        "button");
      message = browserBundle.GetStringFromName("openid.enteropenid");
      button.setAttribute("label", message);
      var callback = function(aEvnt) {
        panel.hidePopup();
        OpenIdNascarUrlbar.openPreferences();
      };
      button.addEventListener("command", callback, false);
      box.insertBefore(button, box.firstChild);
      
      panel.close=true;
      var anchor = doc.getElementById("openid-nascar-url-bar-image"); 
      var position = "after_start";
      var x = 0;
      var y = 0;
      var isContextMenu = false;
      var attributesOverride = false;
      var triggerEvent = aEvent;
      panel.openPopup(
          anchor , 
          position , 
          x , y , 
          isContextMenu, 
          attributesOverride, 
          triggerEvent );
    },
    
    urlbarClick : function _urlbarClick(aEvent) {
//      OpenIdNascarUrlbar._logMessage("urlbar clicked");
      Components.utils.import("resource://openidnascar/inputfields.jsm");
      var doc = gBrowser.selectedBrowser.contentDocument;  
      if (!doc) {
//    	  OpenIdNascarUrlbar._logMessage("urlbar clicked: !doc");
    	  return;
      }
      var popupImage = document.getElementById("openid-nascar-popup-image")
      if (popupImage) {
        popupImage.setAttribute("src", "chrome://openidnascar/content/openid-icon-100x100.png");
      }
      var inputField = findBestInputField(doc, OpenIdNascarUrlbar._logMessage);
      if (!inputField) {
//        OpenIdNascarUrlbar._logMessage("urlbar clicked: no input field found");
        var bundleService = Cc["@mozilla.org/intl/stringbundle;1"].getService(Ci.nsIStringBundleService);
        var browserBundle = bundleService.createBundle("chrome://openidnascar/locale/openid.properties");
        var message = browserBundle.GetStringFromName("openid.noopenidinputfield");
        this.popupMessage(aEvent, message);
        return;
      }
      var result = OpenIdNascarUrlbar.getAllEntries(inputField);
      if (aEvent && aEvent.ctrlKey) {
        this.popupNotification(aEvent, result);
        return;
      }
      var preferredOpenidProvider;
      try {
        var OpenIdStorage = Components.classes['@openinfocard.com/openidstorage;1']
          .getService().wrappedJSObject;
        preferredOpenidProvider = OpenIdStorage.getPreferredOpenID();
//        OpenIdNascarUrlbar._logMessage("urlbarClick preferredOpenidProvider=" +
//            preferredOpenidProvider);
      } catch(e) {
        Components.utils.reportError(e);
        return;
      }
      if (!preferredOpenidProvider) {
//        OpenIdNascarUrlbar._logMessage("urlbarClick !preferredOpenidProvider");
        OpenIdNascarUrlbar.noOpenIdYet(aEvent);
        return;
      }
      OpenIdNascarUrlbar.insertOpenid(preferredOpenidProvider, inputField);
    }
};

